<?php

	class Smerr{
		
		private $E, $log_level, $reporter;
		
		function __construct(){
			$this->log_level = ERROR_LOGGING;
			$this->report_level = error_reporting();
		}
		
		function error_logging($L=null){
			$ol = $this->log_level;
			if(!is_null($L)) $this->log_level = $L;
			return $ol;	
		}
			
		// for sake of consistency
		function error_reporting($L=null){
			return is_null($L) ? error_reporting() : error_reporting($L);
		}
		
		function set_reporter($handler){
			$old = $this->reporter;
			$this->reporter = $handler;	
			return $old;
		}
		
		function restore_reporter(){
			$this->reporter = smout();	
		}
		
		function write($message){
			if($this->E & $this->log_level) error_log($message);
			if($this->E & error_reporting()) $this->report($message); 
			$this->E = 0;
		}
		
		function reporter(){
			if(!$this->reporter) $this->restore_reporter();
			return $this->reporter;
		}
		
		function report($message){
			// if there's no smout, there's no buffer yet and no-one to call
			//if(!sn()->is_invoked('Smout')) return;
			$this->reporter()->report_error($message);
		}
		
		public static function level_constants(){
			static $constants = array(
				1 => 'E_ERROR',
				2 => 'E_WARNING',
				4 => 'E_PARSE',
				8 => 'E_NOTICE',
				16 => 'E_CORE_ERROR',
				32 => 'E_CORE_WARNING',
				64 => 'E_COMPILE_ERROR',
				128 => 'E_COMPILE_WARNING',
				256 => 'E_USER_ERROR',
				512 => 'E_USER_WARNING',
				1024 => 'E_USER_NOTICE',
				2048 => 'E_STRICT',
				4096 => 'E_RECOVERABLE_ERROR',
				8192 => 'E_DEPRECATED',
				16384 => 'E_USER_DEPRECATED',
				30719 => 'E_ALL'				 
			);
			return $constants;
		}
		
		function handle_error($n, $str, $file, $line){
			$this->E = $n;
			$c = Smerr::level_constants();
			$LC = isset($c[$n]) ? $c[$n] : "ERROR $n";
			$message = "[$LC] $str in <b>$file</b> on line <b>$line</b>";	
			switch($n){
				case E_ERROR:
				case E_USER_ERROR:
					$this->write($message);
					if(is_numeric($n = substr($str, 0, 3))) httpE($n, substr($str, 3));
					die();
				default:
					$this->write($message);
					return true;	
			}
		}
		
		// we're a pseudo-stream, so we can expect calls to open() and close(), and maybe attempts to read. Just silently return null
		function __call($m, $p){}
	
	}


